﻿// Veizu.Common
// EnumHelper.cs
// 日期:  2018-11-22 15:57
// 公司:           松山湖材料实验室
// 功能:
// 作者:           陈琦

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace RoboSensors.Tools
{
    public static class EnumHelper
    {
        public static T GetInstance<T>(string member)
        {
            return ConvertHelper.ConvertTo<T>(Enum.Parse(typeof(T), member, true));
        }

        public static short[] GetEnumShortValues<T>()
        {
            var tempSelTypes = GetMemberValues<T>();
            var selTypes = new short[tempSelTypes.Length];
            int i = 0;
            foreach (var tempSelType in tempSelTypes)
            {
                selTypes[i] = Convert.ToInt16(tempSelType);
                i++;
            }
            return selTypes;
        }
        public static Dictionary<string, object> GetMemberKeyValue<T>()
        {
            string[] memberNames = GetMemberNames<T>();
            string[] array = memberNames;
            return array.ToDictionary(text => text, GetMemberValue<T>);
        }
        public static string[] GetNames(Type t)
        {
            return Enum.GetNames(t);
        }
        public static string[] GetMemberNames<T>()
        {
            return Enum.GetNames(typeof(T));
        }

        public static string GetMemberName<T>(object member)
        {
            Type underlyingType = GetUnderlyingType(typeof(T));
            object value = ConvertHelper.ConvertTo(member, underlyingType);
            return Enum.GetName(typeof(T), value);
        }

        public static Array GetMemberValues<T>()
        {
            return Enum.GetValues(typeof(T));
        }

        public static object GetMemberValue<T>(string memberName)
        {
            Type underlyingType = GetUnderlyingType(typeof(T));
            T instance = GetInstance<T>(memberName);
            return ConvertHelper.ConvertTo(instance, underlyingType);
        }

        public static Type GetUnderlyingType(Type enumType)
        {
            return Enum.GetUnderlyingType(enumType);
        }

        public static bool IsDefined<T>(string member)
        {
            return Enum.IsDefined(typeof(T), member);
        }

        public static string GetDescription(Type t, object v)
        {
            try
            {
                FieldInfo field = t.GetField(smethod_0(t, v));
                DescriptionAttribute[] array = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
                return (array.Length > 0) ? array[0].Description : smethod_0(t, v);
            }
            catch
            {
                return "UNKNOWN";
            }
        }

        private static string smethod_0(Type type0, object object0)
        {
            try
            {
                return Enum.GetName(type0, object0);
            }
            catch
            {
                return "UNKNOWN";
            }
        }

        public static SortedList GetStatus(Type t)
        {
            SortedList sortedList = new SortedList();
            Array values = Enum.GetValues(t);
            for (int i = 0; i < values.Length; i++)
            {
                string value = values.GetValue(i).ToString();
                int num = (int)Enum.Parse(t, value);
                string description = GetDescription(t, num);
                sortedList.Add(num, description);
            }
            return sortedList;
        }
        public static short Enum2Short<T>(this string enumName)
        {
            T temp = (T)Enum.Parse(typeof(T), enumName);
            var obj = temp as object;
            return Convert.ToInt16(obj);
        }
        public static object ToEnumString<T>(this short num)
        {
            return ((T)Enum.ToObject(typeof(T), num)).ToString();
        }
        public static T ToEnum<T>(this int num)
        {
            return (T)Enum.ToObject(typeof(T), num);
        }
        public static T ToEnum<T>(this short num)
        {
            return (T)Enum.ToObject(typeof(T), num);
        }
        public static object String2EnumByType(this string num, Type t)
        {
            return Enum.Parse(t, num);
        }
        public static object Long2EnumByType(this long num, Type t)
        {
            return Enum.ToObject(t, num);
        }
        public static T ToEnum<T>(this long num)
        {
            var temp = (short)num;
            return temp.ToEnum<T>();
        }
        public static T ToModel<T>(this Enum enumName, string libName, params object[] parameters) where T : class, new()
        {
            return ReflectionHelper.CreateInstance(libName, enumName.ToString(), null, parameters) as T;
        }
        /// <summary>
        /// 得到枚举的中文注释
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static string GetEnumDesc(this Enum e)
        {
            FieldInfo enumInfo = e.GetType().GetField(e.ToString());
            DescriptionAttribute[] enumAttributes = (DescriptionAttribute[])enumInfo.
                GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (enumAttributes.Length > 0)
            {
                return enumAttributes[0].Description;
            }
            return e.ToString();
        }
        /// <summary>
        /// 获取自定义的特性信息，只支持单个属性的特性类型
        /// </summary>
        /// <typeparam name="TAttribute">特性的类型</typeparam>
        /// <typeparam name="TVal">特性的值</typeparam>
        /// <param name="e">枚举类型</param>
        /// <returns>特性的值</returns>
        public static TVal GetAttributeValue<TAttribute, TVal>(this Enum e) where TAttribute : Attribute
        {
            FieldInfo enumInfo = e.GetType().GetField(e.ToString());
            var enumAttributes = enumInfo.
                GetCustomAttributes(typeof(TAttribute), false);
            if (enumAttributes.Length > 0)
            {
                var model = (TAttribute)enumAttributes[0];
                var temp = model.GetPropertys().FirstOrDefault(s => s.Type == typeof(TVal));
                if (temp == null)
                    throw new Exception(string.Format("在{0}的特性结构中没有找到类型为{1}的属性", typeof(TAttribute), typeof(TVal)));
                return (TVal)temp.Value;
            }
            return default(TVal);
        }
        public static Dictionary<TEnum, TAttribute> Enum2CustomAttribute<TAttribute, TEnum>(this Type type) where TAttribute : Attribute
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsEnum) throw new ArgumentException("参数必须是枚举类型", type.Name);

            Array array = Enum.GetValues(type);
            var result = new Dictionary<TEnum, TAttribute>();
            foreach (var e in array)
            {
                FieldInfo enumInfo = e.GetType().GetField(e.ToString());
                var enumAttributes = enumInfo.
                    GetCustomAttributes(typeof(TAttribute), false);
                if (enumAttributes.Length > 0)
                {
                    var model = (TAttribute)enumAttributes[0];

                    result.Add((TEnum)e, model);
                }
            }
            return result;
        }
        public static Dictionary<TEnum, TVal> Enum2AttributeDictionary<TEnum, TAttribute, TVal>(this Type type) where TAttribute : Attribute
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsEnum) throw new ArgumentException("参数必须是枚举类型", type.Name);
            Array array = Enum.GetValues(type);
            var result = new Dictionary<TEnum, TVal>();
            foreach (Enum value in array)
            {
                result.Add((TEnum)Enum.Parse(type, value.ToString()), GetAttributeValue<TAttribute, TVal>(value));
            }
            return result;
        }

        //public static TAttribute GetAttribute<TAttribute>(this Type e) where TAttribute : Attribute
        //{
        //    FieldInfo enumInfo = e.GetField(e.ToString());
        //    var enumAttributes = enumInfo.
        //        GetCustomAttributes(typeof(TAttribute), false);
        //    if (enumAttributes.Length > 0)
        //    {
        //        var model = (TAttribute)enumAttributes[0];
        //        return model;
        //    }
        //    throw new MicromachException(string.Format("没有找到该属性的特性{0}", typeof(TAttribute)));
        //}

        public static Dictionary<T, string> Enum2Dictionary<T>(this Type type)
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsEnum) throw new ArgumentException("参数必须是枚举类型", type.Name);

            // List<EnumModel> list = new List<EnumModel>();
            Array array = Enum.GetValues(type);
            var result = new Dictionary<T, string>();
            foreach (var temp in array)
            {
                result.Add((T)temp, GetEnumDesc((Enum)temp));
            }
            return result;
        }
        public static Dictionary<long, string> Enum2Dictionary(this Type type)
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsEnum) throw new ArgumentException("参数必须是枚举类型", type.Name);

            // List<EnumModel> list = new List<EnumModel>();
            Array array = Enum.GetValues(type);
            //int count = 0;
            return array.Cast<Enum>().ToDictionary(value => Convert.ToInt64(Enum.Parse(type, value.ToString())), GetEnumDesc);
        }
        public static Dictionary<long, string> Enum2DictionaryNoDes(this Type type)
        {
            if (type == null) throw new ArgumentNullException();
            if (!type.IsEnum) throw new ArgumentException("参数必须是枚举类型", type.Name);

            // List<EnumModel> list = new List<EnumModel>();
            Array array = Enum.GetValues(type);
            //int count = 0;
            return array.Cast<Enum>().ToDictionary(value => Convert.ToInt64(Enum.Parse(type, value.ToString())), s => s.ToString());
        }

        public static Dictionary<T2, T3> ToDictionary<T1, T2, T3>(List<T1> models, string key = "Id", string val = "Value")
        {
            var result = new Dictionary<T2, T3>();
            foreach (var model in models)
            {
                long id = 0;
                T3 t = default(T3);
                var clsModels = model.GetPropertys();
                foreach (var clsModel in clsModels)
                {

                    if (clsModel.Name == key)
                    {
                        id = (long)clsModel.Value;
                    }
                    else if (clsModel.Name == val)
                    {
                        t = (T3)clsModel.Value;
                    }
                }
                result.Add(id.ToEnum<T2>(), t);
            }
            return result;
        }

        public static long Enum2Long<T>(this T t)
        {
            if (!(t is Enum))
                throw new Exception(string.Format("{0}不是枚举类型，请检查！", t.GetType()));
            return Convert.ToInt64(t);
        }
    }
}